package com.geek.javase.ch18.videodemo.reflect.singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/*
 *@Date 2025/11/7
 *@Author wangpeng
 *@Description TODO
 */

//防御反射策略
public class SingletonDemo3 {
    //私有的 静态的 本类实例
    //private static SingletonDemo3 instance;
    private volatile static SingletonDemo3 instance;

    //标记  随意命名，尽量不要让其他人通过反射获取此私有变量，猜到这个用途
    private static boolean fyfscl = false;

    //私有的构造方法
    private SingletonDemo3() {
        synchronized (SingletonDemo3.class) {
            if (!fyfscl) {
                fyfscl = true;
            }else {
                throw new IllegalArgumentException("该类已经有了实例，不可再进行构造！");
            }
        }
    }

    //公开的 静态的 获得本类实例的方法
    public static SingletonDemo3 getInstance() {
        if (instance == null) {
            synchronized (SingletonDemo3.class) {
                if (instance == null) {
                    instance = new SingletonDemo3();
                }
            }
        }
        return instance;
    }
}

class Test3 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        System.out.println("2.通过反射获取实例");
        //通过反射获取私有构造器
        Class<SingletonDemo3> clazz = SingletonDemo3.class;
        Constructor<SingletonDemo3> declaredConstructor = clazz.getDeclaredConstructor();
        //取消访问权限检查
        declaredConstructor.setAccessible(true);
        //创建实例
        SingletonDemo3 s1 = declaredConstructor.newInstance();
        System.out.println(s1);

        //但是！通过反射获取fyfscl标记，修改标记之后还是可以破坏单例的！
        Field field = clazz.getDeclaredField("fyfscl");
        field.setAccessible(true);
        field.set(s1, false);

        SingletonDemo3 s2 = declaredConstructor.newInstance();
        System.out.println(s2);

        System.out.println(s1 == s2);
    }
}

